package com.fw.core;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fw.config.Constants;
import com.fw.config.FwConfig;
import com.fw.handler.Handler;
import com.fw.log.Logger;

public class FwFilter implements Filter {

	private Handler handler;
	private String encoding;
	private FwConfig fwConfig;
	private Constants constants;
	private static final Fw fw = Fw.me();
	private static Logger log;
	private int contextPathLength;

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		createFwConfig(filterConfig.getInitParameter("configClass"));

		if (fw.init(fwConfig, filterConfig.getServletContext()) == false) {
			throw new RuntimeException("FW init error!");
		}

		handler = fw.getHandler();
		constants = Config.getConstants();
		encoding = constants.getEncoding();
		fwConfig.afterFwStart();

		String contextPath = filterConfig.getServletContext().getContextPath();
		contextPathLength = (contextPath == null || "/".equals(contextPath) ? 0 : contextPath.length());
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		request.setCharacterEncoding(encoding);

		String target = request.getRequestURI();
		if (contextPathLength != 0) {
			target = target.substring(contextPathLength);
		}

		boolean[] isHandled = { false };
		try {
			handler.handle(target, request, response, isHandled);
		} catch (Exception e) {
			if (log.isErrorEnabled()) {
				String qs = request.getQueryString();
				log.error(qs == null ? target : target + "?" + qs, e);
			}
		}

		if (isHandled[0] == false) {
			chain.doFilter(request, response);
		}
	}

	@Override
	public void destroy() {
		fwConfig.beforeFwStop();
		fw.stopPlugins();
	}

	private void createFwConfig(String configClass) {
		if (configClass == null) {
			throw new RuntimeException("Please set configClass parameter of fw in web.xml");
		}
		try {
			Object temp = Class.forName(configClass).newInstance();
			if (temp instanceof FwConfig) {
				fwConfig = (FwConfig) temp;
			} else {
				throw new RuntimeException("Can not create instance of class: " + configClass + ". Please check the config in web.xml");
			}
		} catch (InstantiationException e) {
			throw new RuntimeException("Can not create instance of class: " + configClass, e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException("Can not create instance of class: " + configClass, e);
		} catch (ClassNotFoundException e) {
			throw new RuntimeException("Class not found: " + configClass + ". Please config it in web.xml", e);
		}
	}

	static void initLogger() {
		log = Logger.getLogger(FwFilter.class);
	}
}
